/**
 * @file ws2812.h
 * @author realTiX: realticks@qq.com
 * @brief ws2812 stm32 spi dma driver
 *        spi speed: 4 MBits/s
 *        spi first bit: MSB
 * @version 0.1
 * @date 2025-01-18
 * 
 * @copyright Copyright (c) 2025
 * 
 */

#ifndef __WS2812_H_
#define __WS2812_H_

#include "main.h"

// 需要使用 DMA 发送完成中断则打开此宏
// #define NEED_DMA_SEND_OVER_IT

#define WS2812_LAMP_NUM         2
#ifdef NEED_DMA_SEND_OVER_IT
    #define WS2812_RST_BYTES    158
#else
    #define WS2812_RST_BYTES    1
#endif

extern uint8_t ws2812Buffer[WS2812_LAMP_NUM * 3 * 8 * 4 / 8 + WS2812_RST_BYTES];

#define WS2812_0_CODE           0x8     // 0b1000
#define WS2812_1_CODE           0xE     // 0b1110

#define WS2812_00_CODE          0x88
#define WS2812_01_CODE          0x8E
#define WS2812_10_CODE          0xE8
#define WS2812_11_CODE          0xEE

#define WS2812_0000_0000_CODE   0x88888888
#define WS2812_1111_1111_CODE   0xEEEEEEEE

typedef struct {
    uint32_t green;
    uint32_t red;
    uint32_t blue;
}ws2812ColorStu;

/* 废弃
struct ws2812ColorStu {
    // ws2812: GRB 顺序，高码先行
    // spi：4 Bits 作 wa2812 1 位，高位先行
    // 结构体：低地址先行，放高码
    uint32_t G0:4;
    uint32_t G1:4;
    uint32_t G2:4;
    uint32_t G3:4;
    uint32_t G4:4;
    uint32_t G5:4;
    uint32_t G6:4;
    uint32_t G7:4;
    
    uint32_t R0:4;
    uint32_t R1:4;
    uint32_t R2:4;
    uint32_t R3:4;
    uint32_t R4:4;
    uint32_t R5:4;
    uint32_t R6:4;
    uint32_t R7:4;

    uint32_t B0:4;
    uint32_t B1:4;
    uint32_t B2:4;
    uint32_t B3:4;
    uint32_t B4:4;
    uint32_t B5:4;
    uint32_t B6:4;
    uint32_t B7:4;
};
*/

struct ws2812PixelDescribeStu {
    uint16_t x;
    uint16_t y;

    uint8_t red;
    uint8_t green;
    uint8_t blue;
};

struct ws2812Stu {
    uint8_t *buffer;
    uint16_t lampNum;

    uint16_t (*lampIndexRemap)(uint16_t x, uint16_t y);

    SPI_HandleTypeDef *hspi;
};

void ws2812_set_1_color_index(struct ws2812Stu *ws, struct ws2812PixelDescribeStu *pixel, uint16_t index);
void ws2812_set_1_color_xy(struct ws2812Stu *ws, struct ws2812PixelDescribeStu *pixel);
void ws2812_set_all_color(struct ws2812Stu *ws, uint8_t red, uint8_t green, uint8_t blue);
void ws2812_refresh(struct ws2812Stu *ws);

void ws2812_init(struct ws2812Stu *ws);

uint8_t ws_remap_pixel(uint8_t x, uint8_t y);
// void ws_draw_pixel(struct ws2812Stu *ws, uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b);
void ws_show_digit(struct ws2812Stu *ws, uint8_t number, struct ws2812PixelDescribeStu *pixel);

uint16_t myWs_index_remap(uint16_t x, uint16_t y);

#endif
